#include "mb_store.h"

/* store 私有数据 */
store_prvt s_store_prvt = 
{
    .fw_var.is_addr_offset_reset = MB_FALSE_DEF,
    .fw_var.addr_attr   = {0, MB_FW_MAX_SIZE},
    .info_var.addr_attr = {0, MB_FW_RW_LEN_DEF},
};

/* ------------------------------------------------------------- */

/* ----------------- 存储相关操作 (不向上层展示) ----------------- */

/* 复位 固件存储器的偏移地址 */
static void mb_store_prvt_fw_addr_offset_reset(MB_STATUS IS_FORCE)
{
    /* 每次只复位1次 */
    if (s_store_prvt.fw_var.is_addr_offset_reset != MB_TRUE)
    {
        s_store_prvt.fw_var.cur_addr_offset      = 0;
        s_store_prvt.fw_var.is_addr_offset_reset = MB_TRUE;
        return;
    }

    /* 强制修改 */
    if (IS_FORCE == MB_TRUE)
    {
        s_store_prvt.fw_var.cur_addr_offset      = 0;
        s_store_prvt.fw_var.is_addr_offset_reset = MB_TRUE;
    }

    return;
}

/* 初始化私有变量值 */
static int mb_store_prvt_var_init(void)
{
    /* 固件信息相关变量初始化 */
    s_store_prvt.info_var.cur_addr_offset      = 0;
    s_store_prvt.info_var.is_addr_offset_reset = MB_TRUE;

    /* 固件相关变量初始化 */
    s_store_prvt.fw_var.cur_addr_offset      = 0;
    s_store_prvt.fw_var.is_addr_offset_reset = MB_TRUE;

    return 0;
}

/* ------------------- 存储操作 (向上层展示) 实现 ------------------- */

/* 初始化数据载体 (即数据存储的通道) */
static int store_op_carrier_init(sto_op *op)
{
    /* 为 数据存储 指定数据通道的操作接口 */
    s_store_prvt.carrier = op;

    if (s_store_prvt.carrier == NULL)
    {
        return -1;
    }

    return 0;
}

/* 从所选择的数据载体中拿到指定大小的空闲空间  */
static void store_op_take_free_space(uint32_t size)
{
    mb_addr_attr * addr_attr;

    /* 判断接口是否可用 */
    if (s_store_prvt.carrier == NULL)
    {
        return;
    }

    /* 获得空闲空间, 即接下来可能会存入固件数据 */
    mb_store_prvt_var_init();   /* 初始化私有变量值 */

    /* 获得指定大小的空闲的存储空间 */
    addr_attr = s_store_prvt.carrier->take_free_space(size);

    if (addr_attr == NULL)
    {
        return;
    }

    s_store_prvt.fw_var.addr_attr.addr = addr_attr->addr;
    s_store_prvt.fw_var.addr_attr.len  = addr_attr->len;

    /* 擦除给定的这片存储空间 */
    s_store_prvt.carrier->erase_space(s_store_prvt.fw_var.addr_attr.addr);

    return;
}

/* 保存 (存入) 固件 */
static MB_XFR_STATUS store_op_store_firmware(mb_buf_attr * buf_attr)
{
    uint32_t addr;

    /* 判断接口是否可用 */
    if (s_store_prvt.carrier == NULL)
    {
        return MB_XFR_MODERR;   /* 模块异常 */
    }

    /* 复位 固件存储器的偏移地址 */
    mb_store_prvt_fw_addr_offset_reset(MB_FALSE);

    /* 判断数据有效性 (有无超出获得的空间范围) */
    if ((s_store_prvt.fw_var.cur_addr_offset + buf_attr->len) > \
        s_store_prvt.fw_var.addr_attr.len)
        {
            return MB_XFR_MODERR;   /* 模块异常 */
        }

    /* 存储固件数据 */
    addr = s_store_prvt.fw_var.addr_attr.addr + \
           s_store_prvt.fw_var.cur_addr_offset;

    s_store_prvt.carrier->put_data(buf_attr, addr);

    /* 修改地址偏移值 */
    s_store_prvt.fw_var.cur_addr_offset += buf_attr->len;

    /* (被动完成 MB_XFR_FINISHED ) */
    return MB_XFR_ING;
}

/* 读出固件 */
static mb_buf_attr * store_op_get_firmware(void)
{
    uint32_t      addr;
    mb_buf_attr * buf_attr;

    /* 判断接口是否可用 */
    if (s_store_prvt.carrier == NULL)
    {
        return NULL;
    }

    /* 复位 固件存储器的偏移地址 */
    mb_store_prvt_fw_addr_offset_reset(MB_TRUE);

    /* 判断数据有效性 (有无超出获得的空间范围) */
    if ((s_store_prvt.fw_var.cur_addr_offset + MB_FW_RW_LEN_DEF) > \
        s_store_prvt.fw_var.addr_attr.len)
        {
            return NULL;
        }

    /* 读出固件数据 */
    addr = s_store_prvt.fw_var.addr_attr.addr + \
           s_store_prvt.fw_var.cur_addr_offset;

    buf_attr = s_store_prvt.carrier->get_data(addr, MB_FW_RW_LEN_DEF);

    if (buf_attr == NULL)
    {
        return NULL;
    }

    /* 修改地址偏移值 */
    s_store_prvt.fw_var.cur_addr_offset += buf_attr->len;

    /* (被动完成 MB_XFR_FINISHED ) */
    return buf_attr;
}

/* 存储固件大小 (字节) */
static void store_op_store_firmware_size(void)
{
    mb_buf_attr buf_attr;

    /* 判断接口是否可用 */
    if (s_store_prvt.carrier == NULL)
    {
        return;
    }

    /* 参数校验 */
    if (s_store_prvt.fw_var.cur_addr_offset == 0)
    {
        return;
    }

    /* fw_var.cur_addr_offset 即为 固件大小 */
    s_store_prvt.info_var.size.nbr = s_store_prvt.fw_var.cur_addr_offset;
    buf_attr.buf = s_store_prvt.info_var.size.buf;
    buf_attr.len = sizeof(s_store_prvt.info_var.size.buf);

    /* 保存固件大小到存储设备 */
    s_store_prvt.carrier->put_data(&buf_attr, \
                                   s_store_prvt.info_var.addr_attr.addr);

    /* 初始化私有变量值 (为下次写入做准备) */
    mb_store_prvt_var_init();

    return;
}

/* 获得固件大小 (字节) */
static uint32_t store_op_get_firmware_size(void)
{
    mb_buf_attr * buf_attr;

    /* 判断接口是否可用 */
    if (s_store_prvt.carrier == NULL)
    {
        return 0;
    }

    /* 从存储设备获得固件大小 */
    buf_attr = \
    s_store_prvt.carrier->get_data(s_store_prvt.info_var.addr_attr.addr, \
                                   sizeof(s_store_prvt.info_var.size.buf));

    if (buf_attr != NULL)
    {
        memcpy(s_store_prvt.info_var.size.buf, buf_attr->buf, \
               sizeof(s_store_prvt.info_var.size.buf));
    }

    /* 初始化私有变量值 (为读出做准备) */
    mb_store_prvt_var_init();

    return s_store_prvt.info_var.size.nbr;
}

/* 内存映射(针对从片外存储设备启动) */
static int store_op_memory_mapped(void)
{
    /* 判断接口是否可用 */
    if (s_store_prvt.carrier == NULL)
    {
        return -1;
    }

    /* 内存映射 */
    s_store_prvt.carrier->memory_mapped();

    return 0;
}

/* ----------------------------- 注册指定的STORE操作函数接口 ----------------------------- */

/* store 操作接口 */
store_op s_store_op =
{
    .carrier_init        = store_op_carrier_init,
    .take_free_space     = store_op_take_free_space,
    .store_firmware      = store_op_store_firmware,
    .get_firmware        = store_op_get_firmware,
    .store_firmware_size = store_op_store_firmware_size,
    .get_firmware_size   = store_op_get_firmware_size,
    .memory_mapped       = store_op_memory_mapped,
};

/* 注册 prot 操作 */
store_op_t mb_store_op_register(void)
{
    /* 初始化数据帧中固定的数据值 */
    mb_store_prvt_var_init();

    return &s_store_op;
}
